package cn.melonlib.cores.graphql.comp.web.proxy;

import cn.melonlib.cores.graphql.comp.service.GraphQLService;
import cn.melonlib.cores.graphql.comp.web.bean.GraphqlArguments;
import cn.melonlib.cores.jpa.model.bean.collections.JsonMap;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.ExecutionInput;
import graphql.ExecutionResult;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class GraphqlWebProxy {

    @Resource
    private ObjectMapper jsonMapper;

    @Resource
    private GraphQLService graphQLService;



    public Object reloadSchema() throws Exception {
        graphQLService.buildGraphql();
        Map<String, Object> res = new HashMap<>();
        return this.jsonMapper.writeValueAsString(res);
    }


    /**
     * 私有接口，需要登录
     *
     * @param body
     * @param request
     * @return
     * @throws Exception
     */
    public Object executeGraphQL(GraphqlArguments body, HttpServletRequest request) throws Exception {
        String query = body.getQuery();
        Map<String, Object> variables = body.getVariables();
        ExecutionResult executionResult = graphQLService.getQl()
                .execute(ExecutionInput.newExecutionInput()
                        .query(query)
                        .variables(ObjectUtils.defaultIfNull(variables, new HashMap<>())));
        Map<String, Object> result = new LinkedHashMap<>();
        if (executionResult.getErrors().size() > 0) {
            result.put("errors", executionResult.getErrors());
        }
        result.put("data", executionResult.getData());
        return result;
    }

    public String providerMap(HttpServletRequest request, HttpServletResponse response)throws Exception{
        String auth=request.getHeader("Authorization");
        String service=request.getParameter("service");
//        if(securityConfig.auth(auth)) {
            JsonMap<Object> result=JsonMap.createMap()
                    .append("index",graphQLService.getServiceMap().values().stream().map(vo->vo.getName()).collect(Collectors.toList())
                    )
                    .append("body", StringUtils.isNoneBlank(service) ?graphQLService.getServiceMap().get(service):graphQLService.getServiceMap());
            if (BooleanUtils.toBoolean(request.getParameter("format"))) {
                return jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result);
            } else {
                return jsonMapper.writeValueAsString(result);
            }
//        }else{
//            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
//            response.setHeader("WWW-Authenticate", " Basic realm=\"Valid username and password\"");
//            return JsonMap.createMap().append("code",HttpServletResponse.SC_UNAUTHORIZED).append("msg","你无权访问！！").jsonString();
//        }
    }

    public Object public_executeGraphQL(@RequestBody Map body, HttpServletRequest request) throws Exception {

        String query = (String) body.get("query");
        //logger.info("[GraphQL] query: {}", query);
        Map<String, Object> variables = (Map<String, Object>) body.get("variables");
        ExecutionResult executionResult = graphQLService.getPublicQl()
                .execute(ExecutionInput.newExecutionInput()
                        .query(query)
                        .variables(variables == null ? new HashMap<>() : variables));
        Map<String, Object> result = new LinkedHashMap<>();
        if (executionResult.getErrors().size() > 0) {
            result.put("errors", executionResult.getErrors());
            //logger.error("Errors: {}", executzionResult.getErrors());
        }
        // System.out.println(executionResult.getData().toString());
        result.put("data", executionResult.getData());
        BufferedInputStream in=new BufferedInputStream(new FileInputStream(""));
//        in.readNBytes()
        return result;
    }
}
